package com.tian.service.impl;

import com.alibaba.fastjson.JSON;
import com.tian.common.CommonResult;
import com.tian.dto.*;
import com.tian.entity.ChargeStationGun;
import com.tian.enums.ChargerGunStatusEnum;
import com.tian.enums.ResultCode;
import com.tian.mapper.ChargeStationGunMapper;
import com.tian.service.ChargeStationGunService;
import com.tian.util.DateUtils;
import com.tian.util.StationRedisPreKey;
import lombok.extern.slf4j.Slf4j;
import org.redisson.api.RBucket;
import org.redisson.api.RList;
import org.redisson.api.RedissonClient;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

/**
 * {@code @description:} 充电枪信息
 *
 * @author tianwc 公众号：Java后端技术全栈
 * 在线刷题 1200+java面试题和1000+篇技术文章：<a href="https://woaijava.cc/">博客地址</a>
 * {@code @date:} 2024-03-13 11:10
 * {@code @version:} 1.0
 */
@Slf4j
@Service
public class ChargeStationGunServiceImpl implements ChargeStationGunService {
    @Resource
    private ChargeStationGunMapper chargeStationGunMapper;
    @Resource
    private RedissonClient redissonClient;

    @Override
    public CommonResult<Boolean> add(ChargeStationGunReqDto chargeStationGunReqDto) {
        ChargeStationGun chargeStationGun = new ChargeStationGun();
        BeanUtils.copyProperties(chargeStationGunReqDto, chargeStationGun);
        chargeStationGun.setCreateTime(new Date());
        chargeStationGun.setStatus(ChargerGunStatusEnum.WAIT_ON_SHELF.getChargerStatus());
        chargeStationGunMapper.insert(chargeStationGun);
        RList<String> list = redissonClient.getList(StationRedisPreKey.STATION_GUN_LIST_KEY + chargeStationGun.getStationId());
        list.add(chargeStationGun.getGunNo());
        setRedis(chargeStationGun);
        return CommonResult.success(true);
    }

    @Override
    public CommonResult<Boolean> update(ChargeStationGunReqDto chargeStationGunReqDto) {
        ChargeStationGun chargeStationGun = chargeStationGunMapper.selectByPrimaryKey(chargeStationGunReqDto.getId());
        chargeStationGun.setGunName(chargeStationGunReqDto.getGunName());
        chargeStationGun.setGunNo(chargeStationGunReqDto.getGunNo());
        chargeStationGun.setGunType(chargeStationGunReqDto.getGunType());
        chargeStationGun.setGunPower(chargeStationGunReqDto.getGunPower());
        chargeStationGunMapper.updateByPrimaryKey(chargeStationGun);
        setRedis(chargeStationGun);
        return CommonResult.success(true);
    }

    @Override
    public CommonResult<Boolean> online(ChargeStationGunReqDto chargeStationGunReqDto) {
        ChargeStationGun chargeStationGun = chargeStationGunMapper.selectByPrimaryKey(chargeStationGunReqDto.getId());
        chargeStationGun.setStatus(chargeStationGunReqDto.getStatus());
        chargeStationGunMapper.updateByPrimaryKey(chargeStationGun);
        setRedis(chargeStationGun);
        return CommonResult.success(true);
    }

    @Override
    public CommonResult<Boolean> bind(ChargeStationGunReqDto chargeStationGunReqDto) {
        ChargeStationGun chargeStationGun = chargeStationGunMapper.selectByPrimaryKey(chargeStationGunReqDto.getId());
        chargeStationGun.setStationName(chargeStationGunReqDto.getStationName());
        chargeStationGun.setStationId(chargeStationGunReqDto.getStationId());
        chargeStationGunMapper.updateByPrimaryKey(chargeStationGun);

        // 存储可用的充电枪
        String availableKey = "station_"+chargeStationGun.getStationId()+":available";
        Integer id = chargeStationGunReqDto.getId();
        redissonClient.getSet(availableKey).add(id);
        // 移除不可用的充电枪
        //redissonClient.getSet(availableKey).remove(id);
        // 存储不可用的充电枪
        // String unavailableKey = "station_1:unavailable";
        // redissonClient.getSet(unavailableKey).add(id);
        // 查询可用的充电枪数量
        // long availableCount = redissonClient.getSet(availableKey).size();
        // 查询某个充电枪是否可用
        // boolean isAvailable = redissonClient.getSet(availableKey).contains(id);

        setRedis(chargeStationGun);
        return CommonResult.success(true);
    }

    private void setRedis(ChargeStationGun chargeStationGun) {
        RBucket<String> chargeStationGunBucket = redissonClient.getBucket(StationRedisPreKey.STATION_GUN_PRE_KEY + chargeStationGun.getId());
        chargeStationGunBucket.set(JSON.toJSONString(chargeStationGun));
        RBucket<String> chargeStationGunBucketByNo = redissonClient.getBucket(StationRedisPreKey.STATION_GUN_NO_PRE_KEY + chargeStationGun.getGunNo());
        chargeStationGunBucketByNo.set(JSON.toJSONString(chargeStationGun));
        RBucket<String> chargeStationGunBucketByStationId = redissonClient.getBucket(StationRedisPreKey.STATION_GUN_NO_PRE_KEY + chargeStationGun.getStationId());
        chargeStationGunBucketByStationId.set(JSON.toJSONString(chargeStationGun));
    }

    @Override
    public CommonResult<ChargeStationGunRespDto> queryById(Integer id) {
        RBucket<String> chargeStationGunBucket = redissonClient.getBucket(StationRedisPreKey.STATION_GUN_PRE_KEY + id);
        ChargeStationGun chargeStationGun = JSON.parseObject(chargeStationGunBucket.get(), ChargeStationGun.class);
        if (chargeStationGun == null) {
            chargeStationGun = chargeStationGunMapper.selectByPrimaryKey(id);
            if (chargeStationGun == null) {
                return CommonResult.failed(ResultCode.PARAMETER_ERROR, "充电枪id=" + id + "不存在");
            }
            chargeStationGunBucket.set(JSON.toJSONString(chargeStationGun));

            RBucket<String> chargeStationGunBucketByNo = redissonClient.getBucket(StationRedisPreKey.STATION_GUN_NO_PRE_KEY + chargeStationGun.getGunNo());
            chargeStationGunBucketByNo.set(JSON.toJSONString(chargeStationGun));

            ChargeStationGunRespDto chargeStationGunRespDto = new ChargeStationGunRespDto();
            BeanUtils.copyProperties(chargeStationGun, chargeStationGunRespDto);
            return CommonResult.success(chargeStationGunRespDto);
        }
        ChargeStationGunRespDto chargeStationGunRespDto = new ChargeStationGunRespDto();
        RBucket<String> chargeStationGunBucketByNo = redissonClient.getBucket(StationRedisPreKey.STATION_GUN_NO_PRE_KEY + chargeStationGun.getGunNo());
        chargeStationGunBucketByNo.set(JSON.toJSONString(chargeStationGun));
        BeanUtils.copyProperties(chargeStationGun, chargeStationGunRespDto);
        return CommonResult.success(chargeStationGunRespDto);
    }

    @Override
    public CommonResult<GunQueryPageRespDto> list(ChargeStationGunPageReqDto chargeStationGunPageReqDto) {

        int count = chargeStationGunMapper.count(chargeStationGunPageReqDto);
        if (count == 0) {
            return CommonResult.success(new GunQueryPageRespDto());
        }
        chargeStationGunPageReqDto.setStart((chargeStationGunPageReqDto.getCurrentPage() - 1) * chargeStationGunPageReqDto.getPageSize());
        List<ChargeStationGun> chargeStationGuns = chargeStationGunMapper.selectByPage(chargeStationGunPageReqDto);
        List<GunRespDto> data = new ArrayList<>();
        for (ChargeStationGun chargeStationGun : chargeStationGuns) {
            GunRespDto gunRespDto = new GunRespDto();
            BeanUtils.copyProperties(chargeStationGun, gunRespDto);
            gunRespDto.setCreateTimeStr(DateUtils.format(chargeStationGun.getCreateTime(), DateUtils.FORMAT_SECOND));
            data.add(gunRespDto);
        }
        GunQueryPageRespDto gunQueryPageRespDto = new GunQueryPageRespDto();
        gunQueryPageRespDto.setData(data);
        gunQueryPageRespDto.setTotal(count);
        gunQueryPageRespDto.setCurrentPage(chargeStationGunPageReqDto.getCurrentPage());
        gunQueryPageRespDto.setPageSize(chargeStationGunPageReqDto.getPageSize());
        return CommonResult.success(gunQueryPageRespDto);
    }

    @Override
    public CommonResult<Boolean> repair(ChargeStationGunReqDto chargeStationGunReqDto) {
        log.info("生成维修工单：{}", chargeStationGunReqDto);
        return CommonResult.success(true);
    }
}
